package com.xjy.system.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xjy.common.annotation.DataScope;
import com.xjy.common.constant.UserConstants;
import com.xjy.common.core.domain.TreeSelect;
import com.xjy.common.core.domain.entity.SysBudget;
import com.xjy.common.core.domain.entity.SysRole;
import com.xjy.common.core.mybatisplus.core.ServicePlusImpl;
import com.xjy.common.exception.CustomException;
import com.xjy.common.utils.SecurityUtils;
import com.xjy.system.domain.SysUserRole;
import com.xjy.system.mapper.SysBudgetMapper;
import com.xjy.system.mapper.SysRoleMapper;
import com.xjy.system.service.ISysBudgetService;
import com.xjy.system.service.ISysUserRoleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 预算科目信息Service业务层处理
 *
 * @author xjy
 * @date 2022-02-07
 */
@Service
public class SysBudgetServiceImpl extends ServicePlusImpl<SysBudgetMapper, SysBudget> implements ISysBudgetService {
	@Autowired
	private SysRoleMapper roleMapper;
	@Autowired
	private ISysUserRoleService iSysUserRoleService;

	@Override
	@DataScope(budget = "b")
	public List<SysBudget> selectBudgetList(SysBudget sysBudget) {
		Long id = SecurityUtils.getLoginUser().getUser().getUserId();

		if (SecurityUtils.isAdmin(id)) {
			return baseMapper.selectBudgetListAll(sysBudget);
		} else {
			SysUserRole sysUserRole = iSysUserRoleService.queryById(id);
			return baseMapper.selectBudgetList(sysBudget, sysUserRole.getRoleId());
		}

	}

	@Override
	public SysBudget getByIdInfo(Long id) {
		return getById(id);
	}

	@Override
	public List<TreeSelect> treeselectList(List<SysBudget> list) {
		List<SysBudget> budgetList = buildDeptTree(list);
		return budgetList.stream().map(TreeSelect::new).collect(Collectors.toList());
	}

	@Override
	public String checkDeptNameUnique(SysBudget sysBudget) {
		Long deptId = Validator.isNull(sysBudget.getId()) ? -1L : sysBudget.getId();
		SysBudget info = getOne(new LambdaQueryWrapper<SysBudget>()
			.eq(SysBudget::getSubjectName, sysBudget.getSubjectName())
			.eq(SysBudget::getParentNo, sysBudget.getParentNo())
			.last("limit 1"));
		if (Validator.isNotNull(info) && info.getId().longValue() != deptId.longValue()) {
			return UserConstants.NOT_UNIQUE;
		}
		return UserConstants.UNIQUE;
	}

	@Override
	public int insertBudget(SysBudget sysBudget) {
		// 一级目录
		if (sysBudget.getParentNo() != 0) {
			SysBudget info = getById(sysBudget.getParentNo());
			// 如果父节点不为正常状态,则不允许新增子节点
			if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
				throw new CustomException("科目停用，不允许新增");
			}
			if(StringUtils.isNotBlank(info.getAncestors())){
				sysBudget.setAncestors(info.getAncestors() + "," + sysBudget.getParentNo());
			}else {
				sysBudget.setAncestors(String.valueOf(sysBudget.getParentNo()));
			}

		}
		sysBudget.setDelFlag("0");
		return baseMapper.insert(sysBudget);
	}

	@Override
	public int selectNormalChildrenDeptById(Long id) {
		return count(new LambdaQueryWrapper<SysBudget>()
			.eq(SysBudget::getStatus, 0)
			.apply("find_in_set({0}, ancestors)", id));
	}

	@Override
	public int updateBudget(SysBudget sysBudget) {
		SysBudget newParentBudget = getById(sysBudget.getParentNo());
		SysBudget oldBudget = getById(sysBudget.getId());
		if (Validator.isNotNull(newParentBudget) && StringUtils.isNotBlank(newParentBudget.getAncestors()) && Validator.isNotNull(oldBudget)) {
			String newAncestors = newParentBudget.getAncestors() + "," + newParentBudget.getId();
			String oldAncestors = oldBudget.getAncestors();
			sysBudget.setAncestors(newAncestors);
			updateBudgetChildren(sysBudget.getId(), newAncestors, oldAncestors);
		}
		int result = baseMapper.updateById(sysBudget);
		if (UserConstants.BUDGET_NORMAL.equals(sysBudget.getStatus())) {
			updateParentBudgetStatusNormal(sysBudget);
		}
		return result;
	}

	@Override
	public boolean hasChildByDeptId(Long id) {
		int result = count(new LambdaQueryWrapper<SysBudget>()
			.eq(SysBudget::getParentNo, id)
			.last("limit 1")
		);
		return result > 0;
	}

	@Override
	public int deletebudgetById(Long id) {
		return baseMapper.deleteById(id);
	}

	@Override
	public List<Integer> selectBudgetListByRoleId(Long roleId) {
		SysRole role = roleMapper.selectById(roleId);
		return baseMapper.selectBudgetListByRoleId(roleId, role.isDeptCheckStrictly());
	}

	@Override
	public List<TreeSelect> buildBudgetTreeSelect(List<SysBudget> depts) {
		List<SysBudget> deptTrees = buildDeptTree(depts);
		return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
	}

	private void updateParentBudgetStatusNormal(SysBudget dept) {
		String ancestors = dept.getAncestors();
		Long[] budgetIds = Convert.toLongArray(ancestors);
		if(null != budgetIds){
			update(null, new LambdaUpdateWrapper<SysBudget>()
				.set(SysBudget::getStatus, "0")
				.in(SysBudget::getId, Arrays.asList(budgetIds)));
		}

	}

	public void updateBudgetChildren(Long id, String newAncestors, String oldAncestors) {
		List<SysBudget> children = list(new LambdaQueryWrapper<SysBudget>()
			.apply("find_in_set({0},ancestors)", id));
		for (SysBudget child : children) {
			child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
		}
		if (children.size() > 0) {
			baseMapper.updateBudgetChildren(children);
		}
	}

	/**
	 * 构建前端所需要树结构
	 *
	 * @return 树结构列表
	 */
	public List<SysBudget> buildDeptTree(List<SysBudget> list) {
		List<SysBudget> returnList = new ArrayList<SysBudget>();
		List<Long> tempList = new ArrayList<Long>();
		for (SysBudget budget : list) {
			tempList.add(budget.getId());
		}
		for (SysBudget budget : list) {
			// 如果是顶级节点, 遍历该父节点的所有子节点
			if (!tempList.contains(budget.getParentNo())) {
				recursionFn(list, budget);
				returnList.add(budget);
			}
		}
		if (returnList.isEmpty()) {
			returnList = list;
		}
		return returnList;
	}

	/**
	 * 递归列表
	 */
	private void recursionFn(List<SysBudget> list, SysBudget t) {
		// 得到子节点列表
		List<SysBudget> childList = getChildList(list, t);
		t.setChildren(childList);
		for (SysBudget tChild : childList) {
			if (hasChild(list, tChild)) {
				recursionFn(list, tChild);
			}
		}
	}

	private List<SysBudget> getChildList(List<SysBudget> list, SysBudget t) {
		List<SysBudget> tlist = new ArrayList<SysBudget>();
		for (SysBudget n : list) {
			if (Validator.isNotNull(n.getParentNo()) && n.getParentNo().longValue() == t.getId().longValue()) {
				tlist.add(n);
			}
		}
		return tlist;
	}

	/**
	 * 判断是否有子节点
	 */
	private boolean hasChild(List<SysBudget> list, SysBudget t) {
		return getChildList(list, t).size() > 0;
	}
}
